import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';

import 'package:encrypt/encrypt.dart';
import 'package:flutter/widgets.dart' hide Key;
import 'package:netease_cloud_music_api/utils/encrypt_ext.dart';
import 'package:netease_cloud_music_api/utils/utils.dart';
import 'package:pointycastle/asymmetric/api.dart';

class NeteaseCloudMusicApiCrypto {
  static IV _iv = IV.fromUtf8('0102030405060708');
  static String _presetKey = '0CoJUm6Qyw8W8jud';
  static String _linuxapiKey = 'rFgB&h#%2?^eDg:Q';
  static String _base62 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  static String _publicKey =
      '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgtQn2JZ34ZC28NWYpAUd98iZ37BUrX/aKzmFbt7clFSs6sXqHauqKWqdtLkF2KexO40H1YTX8z2lSgBBOAxLsvaklV8k4cBFK9snQXE9/DDaFt6Rr7iVZMldczhC0JNgTz+SHXT6CBHuX3e9SdB1Ua44oncaTWz7OBGLbCiK45wIDAQAB\n-----END PUBLIC KEY-----';
  static String _eapiKey = 'e82ckenh8dichen8';

  static Encrypted _aesEncrypt(String data, AESMode aesMode, Key key, IV iv) {
    Encrypter encrypter = Encrypter(AES(key, mode: aesMode));
    Encrypted encrypted = encrypter.encrypt(data, iv: iv);
    return encrypted;
  }

  static Encrypted _rsaEncrypt(List<int> data, String key) {
    RSAKeyParser parser = RSAKeyParser();
    Encrypter encrypter = Encrypter(RSAExt(publicKey: parser.parse(key) as RSAPublicKey));
    Encrypted encrypted = encrypter.encryptBytes(data);
    return encrypted;
  }

  static Map<String, dynamic> weapi({required object}) {
    String data = object is Map ? jsonEncode(object) : object;
    Uint8List randomKeyBytes = Uint8List.fromList(List.generate(16, (int index) {
      return _base62.codeUnitAt(Random().nextInt(62));
    }));

    // 内容加密(使用固定秘钥)
    String base64Content = _aesEncrypt(data, AESMode.cbc, Key.fromUtf8(_presetKey), _iv).base64;
    // 内容再次加密(使用随机秘钥 randomKey)
    String params = _aesEncrypt(base64Content, AESMode.cbc, Key(randomKeyBytes), _iv).base64;

    // RSA加密密钥
    String encSecKey = _rsaEncrypt(List.from(randomKeyBytes.reversed), _publicKey).base16;
    return {'params': params, 'encSecKey': encSecKey};
  }

  static Map<String, dynamic> linuxapi({required Map<String, dynamic> object}) {
    String data = jsonEncode(object);
    String params = _aesEncrypt(data, AESMode.ecb, Key.fromUtf8(_linuxapiKey), _iv).base16.toUpperCase();
    return {'eparams': params};
  }

  static Map<String, dynamic> eapi({required String? url, required Map<String, dynamic>? object}) {
    String data = jsonEncode(object);
    String message = 'nobody${url}use${data}md5forencrypt';
    String digest = NeteaseCloudMusicApiUtils.generateMd5(data: message);
    String encryptData = '$url-36cd479b6b5-$data-36cd479b6b5-$digest';
    String params = _aesEncrypt(encryptData, AESMode.ecb, Key.fromUtf8(_eapiKey), _iv).base16.toUpperCase();
    return {'params': params};
  }
}

enum EncryptType { eapi, linuxapi, weapi }